#ifndef __SINGAPOREBUSSERVICESVIEW__
#define __SINGAPOREBUSSERVICESVIEW__

// [[[ begin generated region: do not modify [Generated Includes]
#include <aknview.h>
// ]]] end generated region [Generated Includes]

#include "googlepositioning.h"
#include "positionrequest.h"
#include "SingaporeBusStructures.h"
#include "AsyncFileLoader.h"
#include "IteratorControl.h"
#include "CSingaporeBusGenericView.h"
#include <SingaporeBus.RSG>
#include "e32hashtab.h"
#include "CharUtils.h"
#include "SingaporeBusAppUi.h"
#include "CSingaporeBusGenericView.hrh"
#include "DrawUtils.h"


class CSingaporeBusServicesView : public CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesView>
		{
		
		
		RArray<const CArrivalTimeItem*> iItems;
	public:

		virtual TBool FilterItem(const CArrivalTimeItem* aItem, const TDesC8& aSearchText) { return CSingaporeBusGenericHandler::FilterItem(aItem, aSearchText); }
		virtual TReal32 OrderItem(const CArrivalTimeItem* aItem) { return CSingaporeBusGenericHandler::OrderItem(aItem); }
		virtual TBool ListBoxObserver(const CArrivalTimeItem* aItem, CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType)  { return CSingaporeBusGenericHandler::ListBoxObserver(aItem, aListBox, aEventType); }
		virtual TBool HandleCommandL( const CArrivalTimeItem* aItem, TInt aCommand ) 
			{
			TFunTrace funTrace(__PRETTY_FUNCTION__);
			this->iContainer->iIteratorControl->DrawDeferred();
			switch(aCommand)
				{
				case ESingaporeBusRefreshAll:
					{
					for(TInt i = 0 ; i < iItems.Count() ; ++i)
						CSingaporeBusGenericHandler::HandleCommandL(iItems[i], aCommand);
					return ETrue;
					}
				case ESingaporeBusMarkFavorite:
					{
					// favoriting a service makes the service to be favorite, not the service+busstop
					CSingaporeBusGenericHandler::HandleCommandL(aItem->iService, NULL, aCommand);
					return ETrue;
					}
				default:
					return CSingaporeBusGenericHandler::HandleCommandL(aItem, aCommand);
				}
			}
		virtual CEikListBox* CreateListBoxL()
			{
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			const TInt minHeight = doc->iSingaporeBusDrawItemsSG->PrimaryFont()->FontMaxHeight() + doc->iSingaporeBusDrawItemsSG->SecondaryFont()->FontMaxHeight()*2;
			return ConstructListBoxL(
					new (ELeave) CSingaporeBusListBox,
					minHeight + (ClientRect().Height() % minHeight)/(ClientRect().Height() / minHeight)
					);
			}
		virtual void FormatItem(TDes& aBuf, const CArrivalTimeItem* aItem)
			{
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			aBuf.Format(_L("6\t%S to %S @ %S"),
					narrowToWideLC(aItem->iService->iName), narrowToWideLC(aItem->iService->iTo),
					narrowToWideLC(aItem->iStation->iAddress2));
			CleanupStack::PopAndDestroy(3);
			if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
				{
				TReal32 distance = 0;
				doc->iPosition.Distance(aItem->iStation->iCoord, distance);
				aBuf.AppendFormat(_L("(%.0fm)"), distance);
				}
			aBuf.AppendFormat(_L("\t"));
			switch(aItem->iRequestStatus)
				{
				case CArrivalTimeQuery::ERequestWait:
					aBuf.AppendFormat(_L("select to request"));
					break;
				case CArrivalTimeQuery::ERequestPending:
					aBuf.AppendFormat(_L("requesting..."));
					break;
				case CArrivalTimeQuery::ERequestPendingInitialization:
					aBuf.AppendFormat(_L("waiting initialisation..."));
					break;
				case CArrivalTimeQuery::ERequestCompleted:
					aBuf.AppendFormat(_L("%S \xf814 %S"), aItem->iNextBus, aItem->iSubsequentBus);
					break;
				case CArrivalTimeQuery::ERequestUnavailable:
					aBuf.AppendFormat(_L("arrival time unavailable"));
					break;
				case CArrivalTimeQuery::ERequestError:
					aBuf.AppendFormat(_L("error (%S, %S)"), aItem->iNextBus, aItem->iSubsequentBus);
					break;
				}
			aBuf.AppendFormat(_L("\t"));
			
			{
			TBuf8<128> favoriteStr;
			doc->StoreFavoriteL(favoriteStr, aItem->iService);
			TBool isFavorite = EFalse;
			for(TInt i = 0 ; i < doc->iFavorites.Count() && !isFavorite; ++i)
				isFavorite = ((doc->iFavorites[i])->Find(favoriteStr) != NULL);
			if(isFavorite)
				aBuf.Append('0');
			}
			
			}

		
		void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aItem,
				TInt aItemIndex, const TRect& aActualItemRect,
				TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
				TBool aItemIsSelected)
			{
			
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

			if(aItem->iService->iOperator == _L8("TFL"))
				doc->iSingaporeBusDrawItemsLD->DrawBusServiceItemL(aDrawer, aItem, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawBusServiceItemL(aDrawer, aItem, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);

			
			}

				
	void ConstructL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesView>::ConstructL( R_SINGAPORE_BUS_SERVICES_VIEW, R_SINGAPORE_BUS_SERVICES_MARK_MENU, R_SINGAPORE_BUS_STOPS_ICONS, ESingaporeBusServicesViewId );
		}
	
	void NotifyFileLoaded(const CAsyncFileLoader* aFile)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		if(aFile == doc->iServicesFileLoader && iContainer)
			InitializeList();
		}
	
	void NotifyConnected()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			{
			if(iItems[i]->iRequestStatus == CArrivalTimeQuery::ERequestError)
				iItems[i]->iArrivalTimeQuery->SubmitL();
			}
		
		}
	
	void NotifyPositionChange()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			{
			TBuf8<15> upperServiceKey = iItems[i]->iService->iServiceKey;
			upperServiceKey.UpperCase();
			const TStation** pStation = doc->iServicesStationMap->Find(upperServiceKey);
			if(pStation && *pStation != iItems[i]->iStation)
				{
				const TService* service = iItems[i]->iService;
				delete iItems[i];
				iItems[i] = CSingaporeBusGenericHandler::NewArrivalTimeItemL(*pStation, service, this);
				}
			}
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesView>::NotifyPositionChange();
		}

	void DoDeactivate()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		this->SetEmptyUnderlyingL();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			delete iItems[i];
		iItems.Reset();
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesView>::DoDeactivate();
		}
		
	~CSingaporeBusServicesView()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iItems.Close();
	}

		
protected:
	void DoActivateL(
		const TVwsViewId& aPrevViewId,
		TUid aCustomMessageId,
		const TDesC8& aCustomMessage )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesView>::DoActivateL(aPrevViewId, aCustomMessageId, aCustomMessage );
		InitializeList();
		RestoreViewStateL(aCustomMessage);
		}
	
	void InitializeList()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();

		if(!doc->iStationsSortedByStationNumber.Count()) return; // everything must be loaded
		this->SetEmptyUnderlyingL();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			delete iItems[i];
		iItems.Reset();
		for(TInt i = 0 ; i < doc->iServices.Count() ; ++i)
			{
			TBuf8<15> upperServiceKey = doc->iServices[i].iServiceKey;
			upperServiceKey.UpperCase();
			const TStation** pStation = doc->iServicesStationMap->Find(upperServiceKey);
			const TStation* station = NULL;
			if(pStation)
				station = *pStation;
			else
				{
				TStation target = { doc->iServiceStations[doc->iServices[i].iStationsBeg] };
				TInt ret = doc->iStationsSortedByStationNumber.SpecificFindInOrder(&target, TLinearOrder<const TStation*>(&CSingaporeBusDocument::TLinearOrder_Station), EArrayFindMode_Any);
				station = (ret != KErrNotFound) ? doc->iStationsSortedByStationNumber[ret] : NULL;
				}
			if(station)
				iItems.AppendL( CSingaporeBusGenericHandler::NewArrivalTimeItemL(station, &doc->iServices[i], this) );
			}
		if(iItems.Count() > 0)
			this->SetUnderlyingL(
					new (ELeave) CArrayIterator<const CArrivalTimeItem*>(&iItems[0], iItems.Count())
					);	
		}
	
		
	};

#endif // __SINGAPOREBUSSERVICESVIEW__
